package com.funtl.oauth2.server.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;

/**
 * @author: Han.Fu
 * @TIME: 2019/7/14  15:21
 * @Description:
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Bean
    @Primary //除去重复配置(因为spring中自带默认配置,我们加上@Primary注解后, 以我们的为准)
    @ConfigurationProperties(prefix = "spring.datasource") //指定配置文件中的前缀文件
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    //token存数据库(令牌), 将token往数据库中传
    @Bean
    public TokenStore jdbcTokenStore() {
        return new JdbcTokenStore(dataSource());
    }

    //客户端信息, 将客户信息也传入数据库中
    @Bean
    public ClientDetailsService jdbcClientDetails() {
        return new JdbcClientDetailsService(dataSource());
    }

    //oauth2.0不允许明文, 密码需要加密, secret也要进行加密
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    //授权操作
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // (1) 在内存模型中快速进行数据交互, 仅仅只是为了方便Demo的演示
        /*clients
                // 使用内存设置
                .inMemory()
                // client_id
                // Do you authorize "client" to access your protected resources?
                .withClient("client")
                // client_secret
                .secret(passwordEncoder.encode("secret"))
                // 授权类型
                // "authorization_code" 授权码模式
                // "client_credentials" 客户端模式
                // "password" 密码模式
                // "refresh_token"
                .authorizedGrantTypes("authorization_code")//四种,客户端,密码,简单模式,授权码
                // 授权范围
                //  scope.app: 口Approve 口Deny
                .scopes("app")
                // 注册回调地址
                .redirectUris("http://www.baidu.com")
                .refreshTokenValiditySeconds(5000);*/


        // (2)非内存模式 , 读取数据库中的内容
        // 告诉Spring, 我们的client 要走jdbcClient
        clients.withClientDetails(jdbcClientDetails());
    }


    // AuthorizationServerEndpointsConfigurer 端点配置
    // 告诉Spring 我们的token要走jdbcToken
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(jdbcTokenStore());
    }
}
